using QxFramework.Core;
using QxFramework.Utilities;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEngine.SceneManagement;
using Random = UnityEngine.Random;
using System.Reflection;
using System.IO;

namespace App.Common
{
    public class Data : MonoSingleton<Data>
    {
        #region 游戏数据存取接口

        private readonly GameDataContainer _gameDataContainer = new GameDataContainer();

        /// <summary>
        /// 取得游戏数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public T Get<T>(string key = "Default") where T : GameDataBase, new()
        {
            return _gameDataContainer.Get<T>(key);
        }

        /// <summary>
        /// 初始化游戏数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool InitData<T>(out T data, string key = "Default") where T : GameDataBase, new()
        {
            return _gameDataContainer.InitData<T>(out data, key);
        }

        /// <summary>
        /// 设置被修改
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="action"></param>
        /// <param name="key"></param>
        public void SetModify<T>(T t, object modifier, string key = "Default")
            where T : GameDataBase, new()
        {
            _gameDataContainer.SetModify<T>(t, modifier, key);
        }

        /// <summary>
        /// 注册更新监听
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="action"></param>
        /// <param name="key"></param>
        public void RegisterUpdateListener<T>(Action<GameDataBase> action, string key = "Default")
            where T : GameDataBase, new()
        {
            _gameDataContainer.RegisterUpdateListener<T>(action, key);
        }

        /// <summary>
        /// 消除有关某个对象的所有监听
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="obj">添加过监听的对象</param>
        public void RemoveAbout(object obj)
        {
            _gameDataContainer.RemoveAbout(obj);
        }

        [HideInInspector]
        public int CurrentMap = 0;

        /// <summary>
        /// 获取所有注册的数据
        /// </summary>
        /// <returns></returns>
        public Dictionary<string, Dictionary<Type, GameDataContainer.SavedGameData>> GetAllData()
        {
            return _gameDataContainer.GetAll();
        }

        public void SaveToFile(string FileName)
        {
            if (FileName == "")
            {
                return;
            }
            var json = _gameDataContainer.ToSaveJson();
            File.WriteAllText(Application.persistentDataPath+"/" +FileName,json);
        }

        public void LoadFromFile(string FileName)
        {
            try
            {
                var json = File.ReadAllText(Application.persistentDataPath + "/" + FileName);
                _gameDataContainer.FromSaveJson(json);
                LoadLevel(FileName);
            }
            catch (Exception e)
            {
                UIManager.Instance.Open("DialogWindowUI", args: new DialogWindowUI.DialogWindowUIArg
                ("警告", "存档已损坏或不兼容最新版本", null, "确定", () => { }));
                Debug.LogError(FileName);
                return;
            }
        }

        public void DeleteFile(string FileName)
        {
            File.Delete(Application.persistentDataPath + "/" + FileName);
        }

        /// <summary>
        /// 加载关卡的逻辑放在这里
        /// </summary>
        /// <returns></returns>
        public void LoadLevel(string FileName)
        {
            ProcedureManager.Instance.ChangeTo(Launcher.Instance.StartProcedure);
        }


        #endregion 游戏数据存取接口

        #region 变量的声明和初始化     
        public static float Length = 1.7f;

        public float TimeSize = 1;

        public Dictionary<HexaDirect, Vector3> dir2Vector;

        public List<Vector2> pos2World;

        public bool isWin = false;

        public bool inStartUI = true;

        public LevelMap levelMap = null;

        public Vector2 InstantiatePos = Vector2.zero;
        public enum Edge
        {
            None,In,Out
        }

        public enum HexaDirect
        {
            NE=0,
            E=1,
            SE=2,
            WS=3,
            W=4,
            WN=5,
        }

        public enum ChangeType
        {
            RotationClock,
            RotationAntiClock,
            Push,
            ExChange,
        }

        public int levelNum = 1;

        public int nowLevel = 1;
        public int[] cardNum;
        #endregion 变量的声明和初始化

        #region Data类的初始化
        private void Awake()
        {
            DataInit();
        }

        public void DataInit()
        {
            SetTableAgent(); 
            dir2Vector = new Dictionary<HexaDirect, Vector3>();
            dir2Vector[HexaDirect.NE] = new Vector3(1, 0, -1);
            dir2Vector[HexaDirect.E] = new Vector3(1, -1, 0);
            dir2Vector[HexaDirect.SE] = new Vector3(0, -1, 1);
            dir2Vector[HexaDirect.WS] = new Vector3(-1, 0, 1);
            dir2Vector[HexaDirect.W] = new Vector3(-1, 1, 0);
            dir2Vector[HexaDirect.WN] = new Vector3(0, 1, -1);

            pos2World = new List<Vector2>();
            //x
            pos2World.Add(new Vector2(Length*Mathf.Sqrt(3)/2, Length/2));
            //y
            pos2World.Add(new Vector2(-Length * Mathf.Sqrt(3) / 2, Length/2));
            //z
            pos2World.Add(new Vector2(0, -Length));
        }

        public Vector2 getWorldPos(Vector3 vec)
        {
            Vector2 res = InstantiatePos;
            res += (vec.x * pos2World[0] + vec.y * pos2World[1] + vec.z * pos2World[2]);
            return res;
        }

        #endregion

        #region 读表类函数,基层轮子

        private readonly TableAgent _tableAgent = new TableAgent();

        public TableAgent TableAgent
        {
            get { return _tableAgent; }
        }

        public void SetTableAgent()
        {
            var list = ResourceManager.Instance.LoadAll<TextAsset>("Text/Table/");
            for (int i = 0; i < list.Length; i++)
            {
                _tableAgent.Add(list[i].text);
            }
        }

        #endregion 读表类函数,基层轮子

        #region 胜利失败的监听

        public void EndTheGame()
        {
                isWin = true;
                Debug.LogError("用完了卡片");
                UIManager.Instance.Open("DialogWindowUI", "DialogWindowUI", new DialogWindowUI.DialogWindowUIArg("提示", "你用完了卡片", null,"重新开始",()=>
                {
                    LoadLevel(nowLevel);
                    CardManager.Instance.InitCards();
                }));
        }


        public void LoadLevel(int to)
        {
            //旧的
            /*if(SceneManager.GetSceneByName("Level" + nowLevel.ToString()).isLoaded)
            {
                SceneManager.UnloadSceneAsync("Level" + nowLevel.ToString());
            }

            //设置新关卡编号
            nowLevel = to;

            SceneManager.LoadScene("Level" + nowLevel.ToString(),LoadSceneMode.Additive);
            GetComponent<MouseManager>().camera = GameObject.Find("Camera").GetComponent<Camera>();
            GameObject.Find("EndAnim").transform.position = new Vector3(0, 0, -100);*/

            //设置新关卡编号

            if (levelMap != null) 
            {
                Destroy(levelMap.gameObject);
                levelMap = null;
            }


            nowLevel = to;
            GameObject gLevel = GameObject.Find("GLevel");
            if (gLevel != null)
            {
                Destroy(gLevel);
            }
            levelMap = LoadManager.Instance.LoadMapInfo(nowLevel, InstantiatePos);

            //StartCoroutine(new WaitForSeconds(0.5f));
            Invoke("MapLoad", 0.5f);
            
        }

        private void MapLoad()
        {
            Maps.Instance.LoadLevel(levelMap);
            GameObject.Find("Map").GetComponent<LightCheck>().Init();
        }


        #endregion 胜利失败的监听
    }
}